<?php


declare (strict_types = 1);

namespace app\api\traits;

use app\api\traits\exceptions\HttpException;
use GuzzleHttp\Client;
use Psr\Http\Message\ResponseInterface;
use think\facade\Log;
use think\facade\Request;
use GuzzleHttp\Exception\RequestException;


trait YiRequest
{
    protected function get($endpoint, $query = [], $headers = [] ,$desc = "拼接?参数，需要写在query里面。不然不识别参数")
    {
        try {
            return $this->request('get', $endpoint, [
                'headers' => $headers,
                'query' => $query,
            ]);
        }  catch (\Exception $e) {
            Log::write("异常信息：".json_encode($e->getCode()));
            $logInfo = [
                '[ PHP URL ] ' . Request::instance()->url(),
                '[ 请求地址 ] ' . var_export($endpoint, true),
                ' [ 请求Header ] ' . var_export($headers, true),
                ' [ 请求参数 ] ' . var_export($query, true),
                '[ 远端响应 ] ' . json_encode( $e->getMessage(),JSON_UNESCAPED_UNICODE),
                '---------------------------------------------------------------',
            ];
            Log::write("请求参数：".json_encode($query));
            $logInfo = implode(PHP_EOL, $logInfo) . PHP_EOL;
            Log::record($logInfo,'error');
            throw new HttpException($e->getMessage(), $e->getCode());
        }
    }

    protected function post($endpoint, $params = [], $headers = [])
    {
        try{
            return $this->request('post', $endpoint, [
                'headers' => $headers,
                'form_params' => $params,
            ]);
        }  catch (\Exception $e) {
            Log::write("异常信息：".json_encode($e->getCode()));
            $logInfo = [
                '[ PHP URL ] ' . Request::instance()->url(),
                '[ 请求地址 ] ' . var_export($endpoint, true),
                ' [ 请求Header ] ' . var_export($headers, true),
                ' [ 请求参数 ] ' . var_export($params, true),
                '[ 远端响应 ] ' . json_encode( $e->getMessage(),JSON_UNESCAPED_UNICODE),
                '---------------------------------------------------------------',
            ];
            Log::write("请求参数：".json_encode($params));
            $logInfo = implode(PHP_EOL, $logInfo) . PHP_EOL;
            Log::record($logInfo,'error');
//            throw new HttpException($e->getMessage(), $e->getCode(), $e);
            throw new HttpException($e->getMessage(), $e->getCode());
        }
    }
    protected function postJson($endpoint, $params = [],$headers = [],$verify=true,$timeout=60)
    {
        $result = null;
        try {
            $result = $this->unwrapResponse(
                $this->getHttpClient($this->getBaseOptions())->post($endpoint, [
                    'json' => $params,
                    "verify"=>$verify,
                    'headers' => $headers,
                    'timeout'=>$timeout,
                ])
            );
        }  catch (\Exception $e) {

            Log::write("异常信息：".json_encode($e->getCode()));
            $logInfo = [
                '[ PHP URL ] ' . Request::instance()->url(),
                '[ 请求地址 ] ' . var_export($endpoint, true),
                ' [ 请求Header ] ' . var_export($headers, true),
                ' [ 请求参数 ] ' . var_export($params, true),
                '[ 远端响应 ] ' . json_encode( $e->getMessage(),JSON_UNESCAPED_UNICODE),
                '---------------------------------------------------------------',
            ];
            Log::write("请求参数：".json_encode($params));
            $logInfo = implode(PHP_EOL, $logInfo) . PHP_EOL;
            Log::record($logInfo,'error');
//            throw new HttpException($e->getMessage(), $e->getCode(), $e);
            throw new HttpException($e->getMessage(), $e->getCode());
        }
        // 记录日志
        $logInfo = [
            ' [ PHP URL ] ' . Request::instance()->url(),
            ' [ 请求地址 ] ' . var_export($endpoint, true),
            ' [ 请求Header ] ' . var_export($headers, true),
            ' [ 请求参数 ] ' . var_export($params, true),
            ' [ 远端响应 ] ' . json_encode($result,JSON_UNESCAPED_UNICODE),
            '---------------------------------------------------------------',
        ];
        $logInfo = implode(PHP_EOL, $logInfo) . PHP_EOL;
        Log::record($logInfo);
        Log::write("参数：".json_encode($params,JSON_UNESCAPED_UNICODE));

        return $result;
    }

    protected function postRaw($endpoint, $params = "")
    {
        return $this->unwrapResponse(
            $this->getHttpClient($this->getBaseOptions())->post($endpoint, [
                'body' => $params
            ])
        );
    }

    protected function request($method, $endpoint, $options = [])
    {
        $result = null;
        try {
            $result = $this->unwrapResponse($this->getHttpClient($this->getBaseOptions())->{$method}($endpoint, $options));

            $logInfo = [
                '[ PHP URL ] ' . Request::instance()->url(),
                '[ 请求址地址 ] ' . var_export($endpoint, true),
                '[ 请求参数 ] ' . var_export($options, true),
                '[ 远端响应 ] ' . json_encode($result,JSON_UNESCAPED_UNICODE),
                '---------------------------------------------------------------',
            ];
            $logInfo = implode(PHP_EOL, $logInfo) . PHP_EOL;
            Log::record($logInfo,'info');

        } catch (\Exception $e) {
            Log::write("异常信息：".json_encode($e));
            $logInfo = [
                '[ PHP URL ] ' . Request::instance()->url(),
                '[ 请求地址 ] ' . var_export($endpoint, true),
                '[ 请求参数 ] ' . var_export($options, true),
                '[ 远端响应 ] ' . json_encode( $e->getMessage(),JSON_UNESCAPED_UNICODE),
                '---------------------------------------------------------------',
            ];
            $logInfo = implode(PHP_EOL, $logInfo) . PHP_EOL;
            Log::record($logInfo,'error');
            throw new HttpException($e->getMessage(), $e->getCode(), $e);
            //("系统开小差了，请重试！", $e->getCode(), $e);
        }
        return $result;
    }

    protected function getHttpClient(array $options = []): Client
    {
        return new Client($options);
    }

    protected function getBaseOptions(): array
    {
        $options = method_exists($this, 'getGuzzleOptions') ? $this->getGuzzleOptions() : [];

        return \array_merge($options, [
//           'verify' => false,// ssl 是否绕过，本地调试
            'base_uri' => method_exists($this, 'getBaseUri') ? $this->getBaseUri() : '',
            'timeout' => method_exists($this, 'getTimeout') ? $this->getTimeout() : 60.0,
            'CURLOPT_INTERFACE'=>rand_ip()
        ]);
    }

    protected function unwrapResponse(ResponseInterface $response)
    {
        $contentType = $response->getHeaderLine('Content-Type');
        $contents = $response->getBody()->getContents();
        $httpCode=$response->getStatusCode();

        Log::write("远端调用，响应状态码：".$httpCode);
        if (false !== stripos($contentType, 'json') || stripos($contentType, 'javascript')) {
            return json_decode($contents, true);
        } elseif (false !== stripos($contentType, 'xml')) {
            return json_decode(json_encode(simplexml_load_string($contents)), true);
        }

        return $contents;
    }

    protected function postJsonNew(string $url,array $param=[],array $header=[])
    {
        $ch = curl_init();     //Start cURL
        curl_setopt($ch, CURLOPT_URL, $url);    //Assign URL
        curl_setopt($ch, CURLOPT_POST, 1);      //Define method as $_POST
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($param));    //Assign HTTP Request body
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);      //Assign HTTP Request Header
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLINFO_HEADER_OUT, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 9);

        $response = curl_exec($ch); //Call API service by cURL
        Log::write("响应：".json_encode($response));
        $info = curl_getinfo($ch);
        curl_close($ch);
        return $response;
    }

    protected function postParam(string $url,array $params=[],array $header=[])
    {
        $client = new Client();
        try {
            // 发送 POST 请求
            $response = $client->post($url, [
                'headers' =>$header,
                'form_params' => $params,
            ]);

            // 获取响应状态码
            $statusCode = $response->getStatusCode();

            // 获取响应体
            $body = $response->getBody()->getContents();
            Log::write("远端调用，响应：".$body);
            return json_decode($body,true);
        } catch (RequestException $e) {
            Log::write("远端调用，响应：".$e->getMessage());
        }
    }
}